package com.csj.lc.service;

import com.alibaba.fastjson.JSON;
import com.csj.lc.base.BaseService;
import com.csj.lc.common.HttpUtils;
import com.csj.lc.entity.*;
import com.csj.lc.entity.dto.ReturnDTO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Service
public class DeviceService extends BaseService {

    public String onlineList(Integer userId, Model model, int pageNo) {

        List<DeviceInfoBean> onlineList = new ArrayList<DeviceInfoBean>();

        Set<String> onlineSet = redisComponent.getZset( "OnlineDevice", 0l, 20l  );
        if(onlineSet != null && !onlineSet.isEmpty()){
            onlineList = deviceMapper.queryDeviceBySet(onlineSet);
        }

        model.addAttribute("pageName","在线设备列表");
        model.addAttribute("pageNo",pageNo);
        model.addAttribute("devList",onlineList);

        //        Operation op = new Operation( userId);
        //        op.setContent("获取在线设备列表，页数为"+pageNo+"");
        //        operationMapper.insert(op);

        return "device/onlineList";
    }

    public DeviceInfoBean getDeviceInfo(int userId , String devId){

        if( ! redisComponent.isZsetExists( "OnlineDevice" , devId) ){
            return null;
        }

//        Operation op = new Operation( userId);
//        op.setContent("获取设备("+devId+")的详情");
//        operationMapper.insert(op);

        return deviceMapper.queryDevice(devId);
    }

    public String hardwareSetPage(Model model,String devId) {
        HardwareParameterBean hpb = hsMapper.queryHardwareParameter(devId);
        if( hpb != null ){
            model.addAttribute("hs",hpb);
            return "device/hsPage";
        }else{
            model.addAttribute("errorMsg","此设备["+ devId +"]无法进行硬件配置，可能是固件非最新版本，可升级后重试。");
            return "device/errorPage";
        }
    }

    public ReturnDTO<Integer> requireUpdateHardwareSet(int userId, String devId,String devName ) throws IOException {

        if( hsMapper.updateDeviceNameById(devId,devName)){

            String path = serverIP + "serverdemo/device/configurationHardware";
            String params = "deviceId=" + devId ;

            // 发送Post请求后，获取返回值
            try{
                String respStr = HttpUtils.GetResponse("POST",path,params);
                if( respStr.equals("true") ){
                    Operation op = new Operation( userId );
                    op.setContent("已对设备(" + devId + ")发送新的硬件配置信息。");
                    operationMapper.insert(op);
                    return new ReturnDTO<Integer>(0,"已发送硬件配置信息，设备会自动重启，请等待设备重连。");
                }else{
                    Operation op = new Operation( userId );
                    op.setContent("对设备(" + devId + ")发送新的硬件配置信息失败。");
                    operationMapper.insert(op);
                    return new ReturnDTO<Integer>(-1,"发送硬件配置信息失败。");
                }
            }catch(Exception ex){
                Operation op = new Operation( userId);
                op.setContent("请求设备(" + devId + ")硬件配置更新失败：无法访问更新服务器。");
                operationMapper.insert(op);
                return new ReturnDTO<Integer>(-2,"请求更新硬件配置失败，无法访问更新服务器。");
            }
        }else{
            Operation op = new Operation( userId);
            op.setContent("请求设备(" + devId + ")硬件配置更新失败：无法修改数据库。");
            operationMapper.insert(op);
            return new ReturnDTO<Integer>(-2,"更新失败，无法修改数据库。");
        }
    }

    public String lightControllerPage(Model model, String devId) {
        try {
            LightControllerParameterBean lcpb = getLCPB( devId);
            if( lcpb == null ){
                model.addAttribute("errorMsg","此设备["+ devId  +"]无法进行灯控配置，可能是固件非最新版本，可升级后重试。");
                return "device/errorPage";
            }

            model.addAttribute("device",deviceMapper.queryDevice((devId)) );
            model.addAttribute("lcpb",lcpb);
            return "device/lcPage";
        }catch(Exception ex){
            ex.printStackTrace();
            return null;
        }
    }

    // 辅助方法：《获取灯控配置》的网络链接，以便更新设备最新的状态到数据库中（ 现在已经用不到了 ）
    private boolean readLCFromDevice ( String devId ){
        try {
            String path = serverIP + "serverdemo/device/readBackLightControllerParameter";
            String params = "deviceId=" + devId;
            String respStr = HttpUtils.GetResponse("POST",path,params); // 访问链接，并更新到数据库
            return respStr.equals("true");
        }catch(Exception ex){
            ex.printStackTrace();
            return false;
        }
    }

    public ReturnDTO<Integer> requireUpdateLC(int userId , String devId, ArrayList<String> sceneData) {
        try{
            LightControllerParameterBean lcpb = getLCPB( devId);
            boolean[][] sceneDataTemp = lcpb.getSceneData();
            for (int sceneIndex = 0; sceneIndex < sceneDataTemp.length; sceneIndex++) {
                for (int switchIndex = 0; switchIndex < 6; switchIndex++) {
                        sceneDataTemp[sceneIndex][switchIndex] = sceneData.contains(sceneIndex + "_" + switchIndex);
                }
            }
            lcpb.setSceneData( sceneDataTemp );
            String lcpbJsonStr = JSON.toJSONString( lcpb );
//            LightControllerBean lcb =  new LightControllerBean();
//            lcb.setDeviceId(devId);
//            lcb.setJsonStr(lcpbJsonStr);
//            lcMapper.updateLightControllerParameter(lcb);

            String path = serverIP + "serverdemo/device/configurationLightControllerParameter";
            String params = "deviceId=" + devId
                    +"&&parameterJsonStr=" + lcpbJsonStr;//请求的参数

            String respStr = HttpUtils.GetResponse("POST",path,params);
            if( respStr.equals("true") ){
                    String msg = "已对设备(" + devId + ")发送新的灯控配置信息。";
                    Operation op = new Operation( userId );
                    op.setContent(msg);
                    operationMapper.insert(op);
                    return new ReturnDTO<Integer>(0,msg+"设备会自动重启，请等待设备重连。");
            }else{
                    String msg = "对设备(" + devId + ")发送新的灯控配置信息失败。";
                    Operation op = new Operation( userId );
                    op.setContent("对设备(" + devId + ")发送新的灯控配置信息失败。");
                    operationMapper.insert(op);
                    return new ReturnDTO<Integer>(-1,msg);
            }
         }catch(Exception ex){
                String msg  = "请求设备(" + devId + ")灯控配置更新失败：无法访问更新服务器。";
                Operation op = new Operation( userId);
                op.setContent(msg);
                operationMapper.insert(op);
                return new ReturnDTO<Integer>(-2,msg);
        }
    }

    // 辅助方法：通过传入的devId,封装lcpb
    private LightControllerParameterBean getLCPB(String devId){

        LightControllerBean lcb =  lcMapper.queryLightControllerParameter(devId);
        if( lcb == null) return null ;

        LightControllerParameterBean lcpb =  JSON.parseObject( lcb.getJsonStr(), LightControllerParameterBean.class);
        return lcpb;
    }

    /**
     * 进入中控配置页面
     * @param model
     * @param devId 设备ID
     * @return
     */
    public String ccPage(Model model, String devId) {
        try {

            model.addAttribute("device",deviceMapper.queryDevice(devId));
            model.addAttribute("protocolList", ccMapper.getProtocolList());
            return "device/ccPage";
        }catch(Exception ex){
            ex.printStackTrace();
            return null;
        }
    }

    /**
     * 根据入参，配置中控协议
     * @param currentUserId
     * @param devId
     * @param protocolId
     * @return
     */
    public ReturnDTO requireUpdateCC(int currentUserId, String devId, int protocolId) {

        try{
            String path = serverIP + "serverdemo/device/configurationProtocol";
            String params = "deviceId=" + devId
                    +"&&protocolId=" + protocolId;//请求的参数

            String respStr = HttpUtils.GetResponse("POST",path,params);
            if( respStr.equals("true") ){
                String msg = "已对设备(" + devId + ")发送新的中控(协议)配置信息。";
                Operation op = new Operation( currentUserId );
                op.setContent(msg);
                operationMapper.insert(op);
                return new ReturnDTO<Integer>(0,msg+"设备会自动重启，请等待设备重连。");
            }else{
                String msg = "对设备(" + devId + ")发送新的中控(协议)配置信息失败。";
                Operation op = new Operation( currentUserId );
                op.setContent("对设备(" + devId + ")发送新的中控(协议)配置信息失败。");
                operationMapper.insert(op);
                return new ReturnDTO<Integer>(-1,msg);
            }
        }catch(Exception ex){
            String msg  = "请求设备(" + devId + ")中控(协议)配置更新失败：无法访问更新服务器。";
            Operation op = new Operation( currentUserId);
            op.setContent(msg);
            operationMapper.insert(op);
            return new ReturnDTO<Integer>(-2,msg);
        }
    }

    public ReturnDTO requireUpdateFirmware(int userId, String devId) throws InterruptedException, IOException {

        String path = serverIP + "serverdemo/device/ota";
        String params = "deviceId=" + devId
                +"&&filePath=C://LCFirmwareFile/JKC-910-AI-V2.xbin";//请求的参数

        // 发送Post请求后，获取返回值
        try{
            String respStr = HttpUtils.GetResponse("POST",path,params);
            if( respStr.equals("true") ){
                Operation op = new Operation( userId);
                op.setContent("请求设备(" + devId + ")升级成功。");
                operationMapper.insert(op);
                return new ReturnDTO<Integer>(0,"开始升级");
            }else{

                Operation op = new Operation( userId);
                op.setContent("请求设备(" + devId + ")升级失败，因设备正在操作中。");
                operationMapper.insert(op);

                return new ReturnDTO<Integer>(-1,"设备正在操作中。");
            }
        }catch(Exception ex){

            Operation op = new Operation( userId);
            op.setContent("请求设备(" + devId + ")升级失败：无法访问升级服务器。");
            operationMapper.insert(op);

            return new ReturnDTO<Integer>(-2,"请求升级失败，无法访问升级服务器。");
        }
    }

    public ReturnDTO<Integer> updateProgress(String devId) {

        String queryStr = "Progress_" + devId;
        String progressStr = redisComponent.getString(queryStr);

        if( progressStr == null ){
            return new ReturnDTO<Integer>(-1,"并不处于升级状态",-2 ,null); //在这段代码里，code实际上是冗余数据，前端并没有用到这个数据
        } else{
            Integer progress = Integer.parseInt(progressStr);

            String msg =  "设备正在升级中...";
            if( progress == -1) msg = "固件升级时发生故障，请重新升级。";
            if( progress == 100) msg = "固件升级成功，设备需重启。请稍候重新刷新页面。";
            ReturnDTO<Integer> result = new ReturnDTO<Integer>( 0 , msg , progress ,null);

            // 如果进度为100或-1，则清理该记录；
            if(progress == 100 || progress == -1){
                redisComponent.removeKey(queryStr);
            }

            return result;
        }
    }


}
